
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>


#include "udpServeur.h"
#define MAX_MSG 100
// 2 caractères pour les codes ASCII '\n' et '\0'
#define MSG_ARRAY_SIZE (MAX_MSG+2)

int udpServeurTest(){
    int ecoute ;
    struct sockaddr_in adresse;

    if( 0 > ( ecoute = socketUdpServeur() ) ){
        exit(EXIT_FAILURE);
    }

    adresse = sockaddrUdpServeur();

    if ( 0 > ( ecouteUdpServeur( ecoute, &adresse) ) ) {
        exit(EXIT_FAILURE);
    }
    if ( 0 > (  attenteUdpServeur(ecoute) ) ) {
        exit(EXIT_FAILURE);


    }
    exit(EXIT_SUCCESS);
}

/**
 * Création de la socket d'écoute 
 */
int socketUdpServeur(){
    int s;

    s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);

    if ( 0 > socket ){
        fprintf(stderr, "ERREUR : socketUdpServeur()\n");
        return -1;
    }
    fprintf(stdout, "Création du socket : OK.\n");
    return s;
}

/**
 * initialisation de l'adresse
 */
struct sockaddr_in sockaddrUdpServeur(){
    struct sockaddr_in adresse;
    adresse.sin_family = PF_INET;
    adresse.sin_addr.s_addr = htonl(INADDR_ANY);
    adresse.sin_port = htons((unsigned short int)4200); 
    fprintf(stdout, "Initialisation de l'adresse : OK.\n");
    return adresse;
}

/**
 * ecoute du socket
 */
int ecouteUdpServeur(int socket, struct sockaddr_in * adresse )
{
    if(0 > ( bind( socket, (struct sockaddr * ) adresse, sizeof(struct sockaddr_in) ) ) ){
        fprintf(stderr, "ERREUR : Echec de liaison du socket en écoute\n");
        return -1;
    }
    fprintf(stdout, "Ecoute du socket : OK.\n");
    return 0;
}

/**
 * attente requete et réponse
 */
int attenteUdpServeur(int socket){
    char msg[MSG_ARRAY_SIZE];
    int tailleMessage, i;
    socklen_t tailleAdresse;
    struct sockaddr_in adresseClient;
    fprintf(stdout, "Attente d'un message client en udp...\n");
    while(1)
    {
        tailleAdresse = sizeof(adresseClient);
        memset(msg, 0x0, MSG_ARRAY_SIZE);
        if ( 0 > ( recvfrom(socket, msg, MSG_ARRAY_SIZE, 0, (struct sockaddr * ) &adresseClient, &tailleAdresse) ) ){
            fprintf(stderr, "ERREUR : Echec de la réception du message\n");
            return -1;
        }
        tailleMessage = strlen(msg);
        if ( 0 < tailleMessage ){
            //adresse du client
            fprintf(stdout, "Réception d'un message du client : %s ...\n", inet_ntoa(adresseClient.sin_addr ) );

            //port du client
            fprintf(stdout, "Port distant : %hu ...\n", ntohs(adresseClient.sin_port) );

            //affichage de la ligne recue
            fprintf(stdout, "Message reçu : %s ...\n", msg );

            // Conversion de cette ligne en majuscules.
            for (i = 0; i < tailleMessage; i++)
                msg[i] = toupper(msg[i]);
        }
        //Renvoi de la ligne convertie au client.
        if (sendto(socket, msg, tailleMessage + 1, 0,
                    (struct sockaddr *) &adresseClient,
                    sizeof(adresseClient)) < 0)
            fprintf(stderr, "Erreur : Échec d'envoi du message\n");
    }

    return 0;   
}

